From: Tim Deegan Date: Thu, 2 Jun 2011 12:16:52 +0000 (+0100) Subject: x86/mm/p2m: Fix locking discipline around log-dirty teardown. X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~10230 X-Git-Url: https://dgit.raspbian.org/%22http:/www.example.com/cgi/%22https:/%22bookmarks://%22Dat/%22http:/www.example.com/cgi/%22https:/%22bookmarks:/%22Dat?a=commitdiff_plain;h=eed8876543b558c781de64973778170a003508e8;p=xen.git x86/mm/p2m: Fix locking discipline around log-dirty teardown. It's not safe to call paging_free_log_dirty_page with the log-dirty lock held. Signed-off-by: Tim Deegan --- diff --git a/xen/arch/x86/mm/paging.c b/xen/arch/x86/mm/paging.c index 1ec6d62fdf..65b53ee7d4 100644 --- a/xen/arch/x86/mm/paging.c +++ b/xen/arch/x86/mm/paging.c @@ -156,10 +156,16 @@ void paging_free_log_dirty_bitmap(struct domain *d) { mfn_t *l4, *l3, *l2; int i4, i3, i2; + struct page_list_head to_free; + struct page_info *pg, *tmp; if ( !mfn_valid(d->arch.paging.log_dirty.top) ) return; + INIT_PAGE_LIST_HEAD(&to_free); + + log_dirty_lock(d); + l4 = map_domain_page(mfn_x(d->arch.paging.log_dirty.top)); for ( i4 = 0; i4 < LOGDIRTY_NODE_ENTRIES; i4++ ) @@ -178,22 +184,28 @@ void paging_free_log_dirty_bitmap(struct domain *d) for ( i2 = 0; i2 < LOGDIRTY_NODE_ENTRIES; i2++ ) if ( mfn_valid(l2[i2]) ) - paging_free_log_dirty_page(d, l2[i2]); + page_list_add_tail(mfn_to_page(l2[i2]), &to_free); unmap_domain_page(l2); - paging_free_log_dirty_page(d, l3[i3]); + page_list_add_tail(mfn_to_page(l3[i3]), &to_free); } unmap_domain_page(l3); - paging_free_log_dirty_page(d, l4[i4]); + page_list_add_tail(mfn_to_page(l4[i4]), &to_free); } unmap_domain_page(l4); - paging_free_log_dirty_page(d, d->arch.paging.log_dirty.top); + page_list_add_tail(mfn_to_page(d->arch.paging.log_dirty.top), &to_free); d->arch.paging.log_dirty.top = _mfn(INVALID_MFN); ASSERT(d->arch.paging.log_dirty.allocs == 0); d->arch.paging.log_dirty.failed_allocs = 0; + + log_dirty_unlock(d); + + /* Return the memory now that we're not holding the log-dirty lock */ + page_list_for_each_safe(pg, tmp, &to_free) + paging_free_log_dirty_page(d, page_to_mfn(pg)); } int paging_log_dirty_enable(struct domain *d) @@ -217,10 +229,8 @@ int paging_log_dirty_disable(struct domain *d) domain_pause(d); /* Safe because the domain is paused. */ ret = d->arch.paging.log_dirty.disable_log_dirty(d); - log_dirty_lock(d); if ( !paging_mode_log_dirty(d) ) paging_free_log_dirty_bitmap(d); - log_dirty_unlock(d); domain_unpause(d); return ret; @@ -672,10 +682,9 @@ void paging_log_dirty_init(struct domain *d, /* This function fress log dirty bitmap resources. */ static void paging_log_dirty_teardown(struct domain*d) { - log_dirty_lock(d); paging_free_log_dirty_bitmap(d); - log_dirty_unlock(d); } + /************************************************/ /* CODE FOR PAGING SUPPORT */ /************************************************/